package org.softee.extractor.sax;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;

import org.softee.extractor.QNameMatcher;
import org.softee.extractor.sax.helper.ResultHandler;
import org.softee.extractor.sax.helper.XmlExtractor;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * A helper class that will split an XML InputStream into separate w3c DOM Documents, or Strings containing XML, whose root elements
 * match a QNameMatcher.
 *
 * Note that this will require all the matched elements to be held in (heap)memory, and that DOM Documents typically
 * will take up about 8 times the memory that the equivalent XML in String form.
 *
 * For more memory efficient operation, perform the splitting using an iterative (event driven) approach using a {@link org.softee.extractor.sax.helper.XmlExtractor} subclass
 *
 * @author morten.hattesen@gmail.com
 *
 */
public class XmlSplitter {
    private final QNameMatcher qNameMatcher;

    public XmlSplitter(QNameMatcher qNameMatcher) {
        this.qNameMatcher = qNameMatcher;
    }

    List<Document> splitDom(InputSource src) throws ParserConfigurationException, SAXException, IOException {
        final List<Document> documents = new ArrayList<Document>();
        ResultHandler<Document> resultHandler = new ResultHandler<Document>() {
            @Override
            public void accept(Document document) {
                documents.add(document);
            }
        };
        XmlExtractor<Document> extractor = XmlExtractorFactory.createDomExtractor(qNameMatcher, resultHandler);
        extractor.process(src);
        return documents;
    }

    List<Document> splitDom(Source src) throws TransformerException, SAXException, ParserConfigurationException {
        final List<Document> documents = new ArrayList<Document>();
        ResultHandler<Document> resultHandler = new ResultHandler<Document>() {
            @Override
            public void accept(Document document) {
                documents.add(document);
            }
        };
        XmlExtractor<Document> extractor = XmlExtractorFactory.createDomExtractor(qNameMatcher, resultHandler);
        extractor.process(src);
        return documents;
    }

    List<String> splitDomString(InputSource src) throws ParserConfigurationException, SAXException, IOException {
        final List<String> strings = new ArrayList<String>();
        ResultHandler<String> resultHandler = new ResultHandler<String>() {
            @Override
            public void accept(String xml) {
                strings.add(xml);
            }
        };
        XmlExtractor<Document> extractor = XmlExtractorFactory.createSerializedDomExtractor(qNameMatcher, resultHandler);
        extractor.process(src);
        return strings;
    }

    List<String> splitDomString(Source src) throws ParserConfigurationException, SAXException, TransformerException {
        final List<String> strings = new ArrayList<String>();
        ResultHandler<String> resultHandler = new ResultHandler<String>() {
            @Override
            public void accept(String xml) {
                strings.add(xml);
            }
        };
        XmlExtractor<Document> extractor = XmlExtractorFactory.createSerializedDomExtractor(qNameMatcher, resultHandler);
        extractor.process(src);
        return strings;
    }

    List<String> splitString(InputSource src) throws ParserConfigurationException, SAXException, IOException {
        final List<String> strings = new ArrayList<String>();
        ResultHandler<String> resultHandler = new ResultHandler<String>() {
            @Override
            public void accept(String xml) {
                strings.add(xml);
            }
        };
        XmlExtractor<String> extractor = XmlExtractorFactory.createStringExtractor(qNameMatcher, resultHandler);
        extractor.process(src);
        return strings;
    }

    List<String> splitString(Source src) throws ParserConfigurationException, SAXException, TransformerException {
        final List<String> strings = new ArrayList<String>();
        ResultHandler<String> resultHandler = new ResultHandler<String>() {
            @Override
            public void accept(String xml) {
                strings.add(xml);
            }
        };
        XmlExtractor<String> extractor = XmlExtractorFactory.createStringExtractor(qNameMatcher, resultHandler);
        extractor.process(src);
        return strings;
    }
}
